package com.emergency.evaluate.service.impl;


import com.emergency.base.domain.*;
import com.emergency.common.util.CommonUtils;
import com.emergency.common.util.IdWorker;
import com.emergency.evaluate.dao.*;
import com.emergency.evaluate.domain.Extract;
import com.emergency.evaluate.domain.Weight;
import com.emergency.evaluate.service.ExtractService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.Date;
import java.util.List;

/**
 * Created by Administrator on 2020/3/12.
 */
@Service
@Transactional
public class ExtractServiceImpl implements ExtractService {


    @Autowired
    private ExtractDao extractDao;
    @Autowired
    private IndicatorDao indicatorDao;
    @Autowired
    private IdWorker idWorker;

    @Autowired
    private WeightDao weightDao;
    @Autowired
    private ScenarDao scenarDao;

    @Autowired
    private ScoreDao scoreDao;

    //查询提取指标
    @Override
    public List<Extract> findAllBySid(Long scenarId) {
        return extractDao.findAllByScenar_id(scenarId);
    }

    //保存临时指标表
    @Override
    public List<Extract>  save(Long scenarId, List<Extract> extractList) {
        for (Extract extract : extractList) {
            scoreDao.deleteByExtract ( extract.getId () );
            //判断是修改权重还是添加指标
            if (!CommonUtils.isNullOrEmpty(extract.getWeight ())&& !CommonUtils.isNullOrEmpty(extractDao.findAllById (extract.getId ())))
            {
                Extract extract1 = extractDao.findAllById ( extract.getId () );
                extract1.setWeight ( extract.getWeight () );
                extractDao.save ( extract1 );
            }
            else
            {
        //删除之前保存过的指标，然后再重新插入
        extractDao.deleteByScenar_id(scenarId);}}

        //添加提取的指标
        for (Extract extract : extractList) {
            Weight weight = weightDao.findAllByIndicatorAndScenar (extract.getIndicator ().getId (), scenarId );
            if (CommonUtils.isNullOrEmpty(extract.getId())) {  //如果提取指标表ID 为空，自动赋值ID和创建时间
                extract.setId(idWorker.nextId());
                extract.setCreateTime(new Date());
            }
            extract.setIndicator(indicatorDao.findAllById(extract.getIndicator().getId()));//提取指标库的指标
            Scenar scenar= scenarDao.findAllById(scenarId);
            extract.setScenar(scenar);

            double w=weight.getWeight ();
            extract.setWeight ( w );
            extractDao.save(extract);
        }
        return extractDao.findAllByScenar_id ( scenarId );
    }

     //删除临时表上的指标
    @Override
    public void deleteById(Long id) {
        extractDao.deleteById (id);
    }





    @Override
    public List<Extract> add(Integer kind,Double[][] matrix) {
        List <Extract> extractList = extractDao.findAllByKind ( kind );

        //获取需要的权重数目
        int n = extractList.size ();

        // Double[][] matrix为成对比较矩阵 如[{0.25,1,1},{2,1,2},{3,1,1}]
        // 数组0,1 位置存放的是影响因素0相对于影响因素1的重要程度:matrix[0][1]=0.25代表 影响因素0的重要程度为影响因素1的重要程度的4分之1
        // 读取对比值

        Double[] column = new Double[n];
        for (int j = 0; j < n; j++) {
            for (int i = 0; i < n; i++) {
                if (column[j] != null) {
                    column[j] = column[j] + matrix[i][j];
                } else {
                    column[j] = matrix[i][j];
                }
            }

        }
        //矩阵归一化
        Double[][] matrixColumn = new Double[n][n];
        for (int j = 0; j < n; j++) {
            for (int i = 0; i < n; i++) {
                matrixColumn[i][j] = matrix[i][j] / column[j];
            }

        }
        //获得行数组
        Double[] line = new Double[n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (line[i] != null) {
                    line[i] = line[i] + matrixColumn[i][j];
                } else {
                    line[i] = matrixColumn[i][j];
                }
            }

        }
        //行归一化获得特征向量
        Double[] w = new Double[n];
        double sum = 0.0;
        for (int i = 0; i < n; i++) {
            sum = sum + line[i];
        }
        for (int i = 0; i < n; i++) {
            w[i] = line[i] / sum;                    //特征向量
        }
        Double[] bw = new Double[n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (bw[i] != null) {
                    bw[i] = bw[i] + matrix[i][j] * w[j];
                } else {
                    bw[i] = matrix[i][j] * w[j];
                }
            }
        }
        double sumR = 0.0;                        //最大特征跟R
        for (int i = 0; i < n; i++) {
            sumR = sumR + bw[i] / (n * w[i]);
        }
        double ci = (sumR - n) / (n - 1);                //矩阵一致性指标
        System.out.println ( "计算出的矩阵一致性指标" + ci + "\n" );
        double ri = ricount ( n );//n阶矩阵的平均一致性指标
        double cr = ci / ri;                        //随机一致性比率
        if (cr >= 0.1) {
            System.out.println ( "权重设置不合理" );
        } else {
            //输出特征向量
            for (int i = 0; i < n; i++) {
                System.out.println ( "特征" + i + "的权重：" + w[i] );
                Weight weight = weightDao.findAllByIndicatorAndScenar ( extractList.get ( i).getIndicator ().getId (),extractList.get ( i ).getScenar ().getId () );
                weight.setWeight ( w[i] );
                weightDao.save ( weight );
                extractList.get ( i ).setWeight ( w[i] );
            }
            extractDao.saveAll ( extractList );

        }
        return extractList;
    }


    private double ricount(int n) {
        double ri=0;
        switch(n)
        {case 1:{ri=0;break;}
            case 2:{ri=0;break;}
            case 3:{ri=0.52;break;}
            case 4:{ri=0.89;break;}
            case 5:{ri=1.12;break;}
            case 6:{ri=1.26;break;}
            case 7:{ri=1.36;break;}
            case 8:{ri=1.41;break;}
            case 9:{ri=1.46;break;}
            case 10:{ri=1.49;break;}
            case 11:{ri=1.52;break;}
            case 12:{ri=1.54;break;}
            case 13:{ri=1.56;break;}
            case 14:{ri=1.58;break;}
            case 15:{ri=1.59;break;}
            default:{ri=1.6;break;}}
        return ri;
    }
}
